package com.ruoyi.web.controller.basedata;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.basedata.domain.*;
import com.ruoyi.basedata.domain.vo.TerminalDbImportantTemplate;
import com.ruoyi.basedata.domain.vo.TerminalsDbProtocol;
import com.ruoyi.basedata.domain.vo.TerminalsXbProtocol;
import com.ruoyi.basedata.service.IMeterSheetsService;
import com.ruoyi.basedata.service.ITerminalsDbService;
import com.ruoyi.basedata.service.IUsageRangeService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.datastatistics.Agreement.GuoXinV1;
import com.ruoyi.system.domain.SysSheetUsers;
import com.ruoyi.system.mapper.SysSheetUsersMapper;
import com.ruoyi.system.service.ISysDeptService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 大档案Controller
 *
 * @author ruoyi
 * @date 2023-09-07
 */
@RestController
@RequestMapping("/basedata/terminalsdb")
public class TerminalsDbController extends BaseController {
    @Autowired
    private ITerminalsDbService terminalsDbService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private IMeterSheetsService meterSheetsService;

    @Autowired
    private SysSheetUsersMapper sysSheetUsersMapper;
    @Autowired
    private IUsageRangeService usageRangeService;

    @Value("${system-params.appKey}")
    public String appKey;
    @Value("${system-params.appSecret}")
    private String appSecret;
    @Value("${system-params.masterKeyDb}")
    private String masterKey;
    @Value("${system-params.productIdDb}")
    private String productId;

    @Value("${system-params.dongJianMasterKeyDb}")
    private String dongJianMasterKey;

    @Value("${system-params.dongJianProductIdDb}")
    private String dongJianProductId;

    /**
     * 大表注册协议id
     */
    private static final String PROTOCOL_DB = "1";

    /**
     * 查询大档案列表
     */
    @PreAuthorize("@ss.hasAnyPermi('basedata:terminalsdb:list,analysis:terminal:comparison,analysis:terminal:dosagestatics')")
    @GetMapping("/listTree")
    public AjaxResult listTree(TerminalsDb terminalsDb) {
        List<TerminalsDb> list = terminalsDbService.selectTerminalsDbList(terminalsDb);
        Long deptId = this.getDeptId();
        SysUser sysUser = getLoginUser().getUser();
        HashMap<String, Object> treeMap = new HashMap<>(5);
        if (!Objects.equals(sysUser.getSystemFlag(), Constants.SYS_FLAG_ADMIN)) {
            // systemFlag不为0的用户根据区域筛选出能看到的大表数据
            LambdaQueryWrapper<SysSheetUsers> wrapper = new LambdaQueryWrapper<>(SysSheetUsers.class);
            wrapper.eq(SysSheetUsers::getSysUserid, sysUser.getUserId().intValue());
            List<SysSheetUsers> sheetUsersList = sysSheetUsersMapper.selectList(wrapper);
            List<Integer> sheetIds = sheetUsersList.stream().map(SysSheetUsers::getSheetid).collect(Collectors.toList());
            list = list.stream().filter(db -> sheetIds.contains(db.getSheetsId())).collect(Collectors.toList());
        }
        if (Objects.equals(sysUser.getSystemFlag(), 0) || Objects.equals(sysUser.getSystemFlag(), 1)) {
            deptId = 0L;
            treeMap.put("id", deptId);
            treeMap.put("label", "所有客户");
        } else {
            treeMap.put("id", deptId);
            treeMap.put("label", deptService.selectDeptById(deptId).getDeptName());
        }
        treeMap.put("children", new ArrayList<HashMap<String, Object>>());
        treeMap.put("deviceType", 2);
        SysDept dept = new SysDept();
        dept.setParentId(deptId);
        // 获取本部门以下所有部门树（不包括本部门）
        List<TreeSelect> deptTree = deptService.selectDeptTreeList(dept);
        // 所有部门，用于获取tenantId
        List<SysDept> allDept = deptService.selectDeptList(new SysDept());
        buildTreeMap(deptTree, allDept, list, treeMap);

        return AjaxResult.success(treeMap);
    }

    /**
     * 区域树
     */
    @PreAuthorize("@ss.hasAnyPermi('basedata:terminalsdb:list,analysis:terminal:comparison,analysis:terminal:dosagestatics')")
    @GetMapping("/listAreaTree")
    public AjaxResult listAreaTree(TerminalsDb terminalsDb, Boolean notShowXbArea) {
        List<TerminalsDb> list = terminalsDbService.selectTerminalsDbList(terminalsDb);
        List<Long> sheetsIds;
        SysUser sysUser = getLoginUser().getUser();
        String tenantId = sysUser.getTenantId();
        HashMap<String, Object> treeMap = new HashMap<>(6);
        MeterSheets condition = new MeterSheets();
        if (notShowXbArea == null || notShowXbArea) {
            condition.setNotShowXbArea(true);
        }
        List<MeterSheets> allSheets = meterSheetsService.selectMeterSheetsList(condition);
        if (!Objects.equals(sysUser.getSystemFlag(), Constants.SYS_FLAG_ADMIN)) {
            // systemFlag不为0的用户根据区域筛选出能看到的大表数据
            LambdaQueryWrapper<SysSheetUsers> wrapper = new LambdaQueryWrapper<>(SysSheetUsers.class);
            wrapper.eq(SysSheetUsers::getSysUserid, sysUser.getUserId().intValue());
            List<SysSheetUsers> sheetUsersList = sysSheetUsersMapper.selectList(wrapper);
            sheetsIds = sheetUsersList.stream().map(e -> NumberUtils.createLong(String.valueOf(e.getSheetid()))).collect(Collectors.toList());
            List<Long> finalSheetsIds = sheetsIds;
            list = list.stream().filter(db -> db.getSheetsId() != null && finalSheetsIds.contains(NumberUtils.createLong(String.valueOf(db.getSheetsId())))).collect(Collectors.toList());
            if (Objects.equals(sysUser.getSystemFlag(), Constants.SYS_FLAG_NORMAL_USER)) {
                list = list.stream().filter(db -> Objects.equals(db.getTenantId(), tenantId)).collect(Collectors.toList());
            }
        } else {
            sheetsIds = allSheets.stream().map(MeterSheets::getId).collect(Collectors.toList());
        }
        buildAreaTree(treeMap, allSheets, sheetsIds, list);

        return AjaxResult.success(treeMap);
    }

    /**
     * 查询大档案列表
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:list')")
    @GetMapping("/list")
    public TableDataInfo list(TerminalsDb terminalsDb) {
        startPage();
        List<TerminalsDb> list = terminalsDbService.selectTerminalsDbList(terminalsDb);
        return getDataTable(list);
    }

    /**
     * 导出大档案列表
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:export')")
    @Log(title = "大表档案", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TerminalsDb terminalsDb) {
        List<TerminalsDb> list = terminalsDbService.selectTerminalsDbList(terminalsDb);
        ExcelUtil<TerminalsDb> util = new ExcelUtil<>(TerminalsDb.class);
        util.exportExcel(response, list, "大档案数据");
    }

    /**
     * 获取大档案详细信息
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(terminalsDbService.selectTerminalsDbById(id));
    }

    /**
     * 新增大档案
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:add')")
    @Log(title = "大档案", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TerminalsDb terminalsDb) {
        List<TerminalsDb> list = terminalsDbService.list(new LambdaQueryWrapper<TerminalsDb>().eq(TerminalsDb::getTerminalId, terminalsDb.getTerminalId()).eq(TerminalsDb::getDelFlag, 0));
        if (null != list && list.size() > 0) {
            return AjaxResult.error("设备编号重复！");
        }
        List<TerminalsDb> list1 = terminalsDbService.list(new LambdaQueryWrapper<TerminalsDb>().eq(TerminalsDb::getImei, terminalsDb.getImei()).eq(TerminalsDb::getDelFlag, 0));
        if (null != list1 && list1.size() > 0) {
            return AjaxResult.error("imei重复！");
        }
        SnowflakeUtils idWorker = new SnowflakeUtils(0, 0);
        String locationFlag = idWorker.nextId() + "";
        terminalsDb.setLocationNb(locationFlag);
        int flag = terminalsDbService.insertTerminalsDb(terminalsDb);
        if (flag > 0) {
            TerminalsDbProtocol redisTerminal = terminalsDbService.selectTerminalsDbProtocolList(terminalsDb).get(0);
            redisCache.setCacheMapValue(RedisKeyName.terminalDbInfo + terminalsDb.getSupplierId(), terminalsDb.getCommunicateAddress(), redisTerminal);
            // 注册设备
            if (null == terminalsDb.getProtocolId()) {
                return error("设备档案新增成功，协议错误，不能注册");
            }
            String platform;
            JSONObject responseBody;
            // AEP平台标识
            int platformAep = 1;
            // OneNET平台标识
            int platformOneNet = 2;
            if (terminalsDb.getSignPlatform() == platformAep) {
                platform = "AEP";
                if ("1015".equals(terminalsDb.getSupplierId())) {
                    responseBody = terminalsDbService.createGuoXinDeviceInAep(appKey, appSecret, dongJianMasterKey, terminalsDb);
                } else {
                    responseBody = terminalsDbService.createGuoXinDeviceInAep(appKey, appSecret, masterKey, terminalsDb);
                }
                if (responseBody == null) {
                    return error(platform + "平台注册失败");
                }
                if (responseBody.getInteger("code") == 0) {
                    String deviceId = JSONObject.parseObject(responseBody.getString("result")).getString("deviceId");
                    terminalsDb.setDeviceId(deviceId);
                    terminalsDbService.updateDeviceId(terminalsDb);
                    return success(platform + " 平台注册成功");
                } else {
                    return error(platform + " 平台注册失败:{}" + responseBody);
                }
            } else if (terminalsDb.getSignPlatform() == platformOneNet) {
                platform = "OneNET";
                try {
                    responseBody = terminalsDbService.createDeviceInOneNet(terminalsDb);
                } catch (Exception e) {
                    return error(platform + "平台注册失败");
                }

                if (responseBody.getInteger("errno") == 0) {
                    String deviceId = responseBody.getJSONObject("data").getString("device_id");
                    terminalsDb.setDeviceId(deviceId);
                    terminalsDbService.updateDeviceId(terminalsDb);
                    return success(platform + "平台注册成功");
                }
            }
        }
        return toAjax(flag);
    }

    /**
     * 修改大档案
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:edit')")
    @Log(title = "大档案", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TerminalsDb terminalsDb) {
        return toAjax(terminalsDbService.updateTerminalsDb(terminalsDb));
    }

    /**
     * 删除大档案
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:remove')")
    @Log(title = "大档案", businessType = BusinessType.DELETE)
    @DeleteMapping("/{IDs}")
    public AjaxResult remove(@NotEmpty(message = "删除对象不能为空") @PathVariable Long[] IDs) {
        return toAjax(terminalsDbService.deleteTerminalsDbByIds(IDs));
    }

    /**
     * 大表档案-换表操作
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminalsdb:edit')")
    @Log(title = "大表档案", businessType = BusinessType.UPDATE)
    @PostMapping("/changeTerminalDb")
    public AjaxResult changeTerminalDb(@RequestBody TerminalsDb terminalsDb) {
        try {

            List<TerminalsDb> listTerminalId = terminalsDbService.list(new LambdaQueryWrapper<TerminalsDb>().eq(TerminalsDb::getTerminalId, terminalsDb.getTerminalIdNew())
                    .eq(TerminalsDb::getDelFlag, 0).ne(TerminalsDb::getId, terminalsDb.getId()));
            if (null != listTerminalId && listTerminalId.size() > 0) {
                return AjaxResult.error("设备编号已存在");
            }

            List<TerminalsDb> listImei = terminalsDbService.list(new LambdaQueryWrapper<TerminalsDb>().eq(TerminalsDb::getImei, terminalsDb.getImeiNew())
                    .eq(TerminalsDb::getDelFlag, 0).ne(TerminalsDb::getId, terminalsDb.getId()));
            if (null != listImei && listImei.size() > 0) {
                return AjaxResult.error("IMEI已存在");
            }
            terminalsDbService.changeTerminalDb(terminalsDb);

            if (null == terminalsDb.getProtocolId() || !PROTOCOL_DB.equals(terminalsDb.getProtocolId())) {
                return error("换表成功,协议错误，不能注册");
            }
            String sign = null;
            JSONObject responseBody;
            if (terminalsDb.getSignPlatform() == 1) {
                sign = "AEP";
                responseBody = terminalsDbService.createGuoXinDeviceInAep(appKey, appSecret, masterKey, terminalsDb);
                if (responseBody == null) {
                    return error("换表成功," + sign + "平台注册失败");
                }
                if (responseBody.getInteger("code") == 0) {
                    String deviceId = JSONObject.parseObject(responseBody.getString("result")).getString("deviceId");
                    terminalsDb.setDeviceId(deviceId);
                    terminalsDbService.updateDeviceId(terminalsDb);
                    return success("换表成功," + sign + "平台注册成功");
                }
            } else if (terminalsDb.getSignPlatform() == 2) {
                sign = "OneNET";
                responseBody = terminalsDbService.createDeviceInOneNet(terminalsDb);
                if (responseBody == null) {
                    return error("换表成功," + sign + "平台注册失败");
                }
                if (Integer.parseInt(responseBody.getString("errno")) == 0) {
                    String deviceId = responseBody.getJSONObject("data").getString("device_id");
                    terminalsDb.setDeviceId(deviceId);
                    terminalsDbService.updateDeviceId(terminalsDb);
                    return success("换表成功," + sign + "平台注册成功");
                }
            } else if (terminalsDb.getSignPlatform() == 3) {
                sign = "netty";
                terminalsDbService.updateDeviceId(terminalsDb);
                return success("换表成功," + sign + "平台注册成功");
            }
            return error("换表成功，" + sign + "平台注册失败");

        } catch (Exception e) {
            logger.error("系统错误", e);
            return AjaxResult.error(500, "系统错误");
        }
    }

    /**
     * 根据区域编号
     *
     * @param AreaCode
     * @return
     */
    @GetMapping("/getTerminalListByAreaCode")
    public AjaxResult getTerminalListByAreaCode(@RequestParam(value = "AreaCode") String areaCode) {
        List<TerminalsDb> list = terminalsDbService.list(new LambdaQueryWrapper<TerminalsDb>().eq(TerminalsDb::getSheetsCode, areaCode)
                .eq(TerminalsDb::getDelFlag, 0));
        return AjaxResult.success(list);
    }

    @Log(title = "导入大表档案", businessType = BusinessType.IMPORT)
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<TerminalsDb> util = new ExcelUtil<>(TerminalsDb.class);
        List<TerminalsDb> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = terminalsDbService.importUser(userList, updateSupport, operName);
        return success(message);
    }


    @PostMapping("/getImportTemplate")
    public void getImportTemplate(HttpServletResponse response) throws Exception {
        ExcelUtil<TerminalDbImportantTemplate> util = new ExcelUtil<>(TerminalDbImportantTemplate.class);
        List<TerminalDbImportantTemplate> list = Collections.singletonList(TerminalDbImportantTemplate.builder().build());
        util.exportExcel(response, list, "大表档案导入模版");
    }

    /**
     * 批量更新大表预警策略
     *
     * @param requestBody requestBody
     * @return AjaxResult
     */
    @PostMapping("/editStrategyBatch")
    public AjaxResult editStrategy(@RequestBody String requestBody) {
        try {
            List<Long> ids = JsonUtils.getList(requestBody, "ids", Long.class);
            String strategy = JsonUtils.getString(requestBody, "strategy");
            String tenant = JsonUtils.getString(requestBody, "tenantId");
            if (CollectionUtils.isNotEmpty(ids) && StringUtils.isNotBlank(strategy)) {
                List<TerminalsDb> list = terminalsDbService.listByIds(ids);
                Set<String> tenantIdSet = list.stream().map(TerminalsDb::getTenantId).collect(Collectors.toSet());
                if (tenantIdSet.size() != 1) {
                    return error("只能为同一客户批量设置预警策略！");
                }
                String tenantId = tenantIdSet.stream().findFirst().get();
                if (!UsageRange.COMMON_FLAG.equals(strategy)) {
                    LambdaQueryWrapper<UsageRange> wrapper = Wrappers.lambdaQuery();
                    wrapper.eq(UsageRange::getTenantId, tenantId)
                            .eq(UsageRange::getStrategy, strategy)
                            .eq(UsageRange::getWarnTargetType, UsageRange.WARN_TARGET_TYPE_DB);
                    List<UsageRange> rangeList = usageRangeService.list(wrapper);
                    if (CollectionUtils.isEmpty(rangeList)) {
                        return error("该策略不适用于终端所属客户！");
                    }
                }

                List<TerminalsDb> updateList = new ArrayList<>(ids.size());
                for (Long id : ids) {
                    TerminalsDb update = new TerminalsDb();
                    update.setId(id);
                    update.setStrategy(strategy);
                    updateList.add(update);
                }
                return toAjax(terminalsDbService.updateBatchById(updateList));
            } else if (StringUtils.isNoneBlank(tenant, strategy)) {
                // 对同一个客户批量更新所有的设备策略
                if (!UsageRange.COMMON_FLAG.equals(strategy)) {
                    LambdaQueryWrapper<UsageRange> wrapper = Wrappers.lambdaQuery();
                    wrapper.eq(UsageRange::getTenantId, tenant)
                            .eq(UsageRange::getStrategy, strategy)
                            .eq(UsageRange::getWarnTargetType, UsageRange.WARN_TARGET_TYPE_DB);
                    List<UsageRange> rangeList = usageRangeService.list(wrapper);
                    if (CollectionUtils.isEmpty(rangeList)) {
                        return error("该策略不适用于终端所属客户！");
                    }
                }
                LambdaUpdateWrapper<TerminalsDb> updateWrapper = Wrappers.lambdaUpdate();
                updateWrapper.eq(TerminalsDb::getTenantId, tenant).eq(TerminalsDb::getDelFlag, 0).set(TerminalsDb::getStrategy, strategy);
                return toAjax(terminalsDbService.update(updateWrapper));
            }
            return AjaxResult.error("更新出错");
        } catch (Exception e) {
            logger.error("更新出错", e);
            return AjaxResult.error(e.toString());
        }
    }

    /**
     * 销表
     *
     * @param id 主键
     * @return 结果
     */
    @PreAuthorize("@ss.hasPermi('basedata:terminaldb:cancelTerminal')")
    @Log(title = "大表档案销表", businessType = BusinessType.UPDATE)
    @PutMapping("/{id}")
    public AjaxResult cancelTerminal(@PathVariable Long id) {
        return toAjax(terminalsDbService.cancelTerminal(id));
    }

    /**
     * 从给定的locationNb中找到那些是已删除的
     *
     * @param searchLocationNb 给定的locationNb
     * @return 已删除的locationNb
     */
    @GetMapping("/getDeletedLocationNbs")
    public AjaxResult getDeletedLocationNbs(@RequestParam("searchLocationNb") List<String> searchLocationNb) {
        if (CollectionUtils.isEmpty(searchLocationNb)) {
            return AjaxResult.success(Collections.EMPTY_LIST);
        }
        LambdaQueryWrapper<TerminalsDb> wrapper = Wrappers.lambdaQuery();
        wrapper.select(TerminalsDb::getLocationNb)
                .in(TerminalsDb::getLocationNb, searchLocationNb)
                .eq(TerminalsDb::getDelFlag, 2);
        List<String> deletedLocationNbs = terminalsDbService.listObjs(wrapper, Object::toString);
        return AjaxResult.success(deletedLocationNbs);
    }

    /**
     * 构建部门大表树
     *
     * @param deptTree   已有的部门树
     * @param allDept    所有部门
     * @param deviceList 所有大表
     * @param treeMap    （入参必须包含一个根节点）返回的树形结构
     */
    @SuppressWarnings("unchecked")
    private void buildTreeMap(List<TreeSelect> deptTree, List<SysDept> allDept, List<TerminalsDb> deviceList, HashMap<String, Object> treeMap) {
        // 创建一个映射，用于快速查找部门节点
        Map<String, HashMap<String, Object>> deptMap = new HashMap<>(10);
        Long topId = MapUtils.getLong(treeMap, "id");

        if (!Objects.equals(topId, 0L)) {
            for (SysDept sysDept : allDept) {
                if (Objects.equals(topId, sysDept.getDeptId())) {
                    deptMap.put(sysDept.getTenantId(), treeMap);
                    break;
                }
            }
        }
        List<HashMap<String, Object>> treeChildren = (List<HashMap<String, Object>>) treeMap.get("children");
        // 遍历部门树，构建初始的树形结构
        for (TreeSelect dept : deptTree) {
            for (SysDept sysDept : allDept) {
                if (Objects.equals(dept.getId(), sysDept.getDeptId())) {
                    HashMap<String, Object> deptNode = new HashMap<>(6);
                    deptNode.put("id", dept.getId());
                    deptNode.put("label", dept.getLabel());
                    deptNode.put("children", new ArrayList<HashMap<String, Object>>());
                    deptNode.put("deviceType", 2);
                    treeChildren.add(deptNode);
                    deptMap.put(sysDept.getTenantId(), deptNode);
                }
            }

        }

        // 遍历大表列表，将大表添加到对应的部门节点下
        for (TerminalsDb db : deviceList) {
            HashMap<String, Object> deviceNode = new HashMap<>(6);
            deviceNode.put("id", db.getTerminalId());
            deviceNode.put("label", db.getTerminalName());
            deviceNode.put("locationNb", db.getLocationNb());
            deviceNode.put("deviceType", 3);

            HashMap<String, Object> deptNode = deptMap.get(db.getTenantId());
            if (deptNode != null) {
                List<HashMap<String, Object>> children = (List<HashMap<String, Object>>) deptNode.get("children");
                children.add(deviceNode);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void buildAreaTree(Map<String, Object> treeMap, List<MeterSheets> allSheets, List<Long> authorizedSheetsIds, List<TerminalsDb> dbList) {
        // 初始化树
        treeMap = treeMap == null ? new HashMap<>(6) : treeMap;
        treeMap.put("id", 0);
        treeMap.put("label", "");
        treeMap.put("code", "0");
        treeMap.put("deviceType", 0);
        treeMap.put("children", new ArrayList<Map<String, Object>>());
        // 用于存储所有节点的Map
        Map<Long, Map<String, Object>> nodeMap = new HashMap<>(authorizedSheetsIds.size());

        // 过滤出所有授权的Sheet
        List<MeterSheets> authorizedSheets = new ArrayList<>();
        for (MeterSheets sheet : allSheets) {
            if (authorizedSheetsIds.contains(sheet.getId())) {
                authorizedSheets.add(sheet);
            }
        }

        // 初始化所有节点
        for (MeterSheets sheet : authorizedSheets) {
            Map<String, Object> node = new HashMap<>(4);
            node.put("id", sheet.getId());
            node.put("pId", sheet.getParentId());
            node.put("label", sheet.getSheetsName());
            node.put("code", sheet.getSheetsCode());
            node.put("deviceType", sheet.getDeviceType());
            List<Map<String, Object>> children = new ArrayList<>(20);
            for (TerminalsDb db : dbList) {
                if (Objects.equals(db.getSheetsId(), sheet.getId().intValue())) {
                    Map<String, Object> deviceNode = new HashMap<>(4);
                    deviceNode.put("id", db.getTerminalId());
                    deviceNode.put("pId", sheet.getId());
                    deviceNode.put("label", db.getTerminalName());
                    deviceNode.put("locationNb", db.getLocationNb());
                    deviceNode.put("deviceType", 3);
                    children.add(deviceNode);
                }
            }
            node.put("children", children);
            nodeMap.put(sheet.getId(), node);
        }

        // 构建树结构
        for (MeterSheets sheet : authorizedSheets) {
            Long parentId = sheet.getParentId();
            if (parentId == null || parentId == 0) {
                // 没有父节点或者父节点不在授权列表中，作为根节点
                List<Map<String, Object>> children = (List<Map<String, Object>>) treeMap.get("children");
                children.add(nodeMap.get(sheet.getId()));
            } else {
                // 有父节点，添加到父节点的children中
                Map<String, Object> parentNode = nodeMap.get(parentId);
                List<Map<String, Object>> children;
                if (parentNode != null) {
                    children = (List<Map<String, Object>>) parentNode.get("children");
                } else {
                    // 没有父节点或者父节点不在授权列表中，作为根节点
                    children = (List<Map<String, Object>>) treeMap.get("children");
                }
                children.add(nodeMap.get(sheet.getId()));
            }
        }
        countDevice(treeMap);
        sortAreaTree(treeMap);
    }

    /**
     * 统计每个区域下有多少个设备，包括子区域
     *
     * @param treeMap 区域树
     * @return 设备数量
     */
    @SuppressWarnings("unchecked")
    private int countDevice(Map<String, Object> treeMap) {
        if (treeMap == null) {
            return 0;
        }
        Integer deviceType = MapUtils.getInteger(treeMap, "deviceType");
        List<Map<String, Object>> children = (List<Map<String, Object>>) treeMap.get("children");
        int deviceCount = (deviceType != null && deviceType == 3) ? 1 : 0;
        if (CollectionUtils.isNotEmpty(children)) {
            for (Map<String, Object> child : children) {
                deviceCount += countDevice(child);
            }
        }

        // 设备类型不是3的是区域
        if (deviceType != null && deviceType != 3) {
            treeMap.put("deviceCount", deviceCount);
        }

        return deviceCount;
    }

    /**
     * 根据设备数量排序树节点
     *
     * @param treeNode 树节点
     */
    @SuppressWarnings("unchecked")
    private void sortAreaTree(Map<String, Object> treeNode) {
        if (treeNode == null) {
            return;
        }
        List<Map<String, Object>> children = (List<Map<String, Object>>) treeNode.get("children");
        if (CollectionUtils.isNotEmpty(children)) {
            // 对 children 按 deviceCount 进行降序排序
            children.sort((a, b) -> {
                Integer countA = MapUtils.getInteger(a, "deviceCount", 0);
                Integer countB = MapUtils.getInteger(b, "deviceCount", 0);
                return -Integer.compare(countA, countB);
            });

            // 递归对每个子节点进行排序
            for (Map<String, Object> child : children) {
                sortAreaTree(child);
            }
        }
    }


}

